package cn.openea.perpartner.mpwx.core;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import me.chanjar.weixin.mp.api.WxMpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * @author Weird077
 * @description TODO
 * @date 2022-06-22 10:45
 */
@Component
public class SendMsgTemplate {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private WxMpService wxMpService;
    @Autowired
    private MsgTypeHandler msgTypeHandler;
    public void setWxMpService(WxMpService wxMpService){
        this.wxMpService = wxMpService;
    }
    /**
     * 发送消息功能
     * 这里有对一部分错误进行补发，当前只对 errcode=40001 或 errcode=40165 时需要将消息补发
     *
     * @param msgobj  消息内容OBJ
     * @param msgType 消息类型 template 表示模板消息
     * @return
     * @throws Exception
     */
    public String sendMsg(JSONObject msgobj, String msgType) {
        String str = sendMsg(msgobj, msgType, false);
        // 如果消息发送是失败的，则再次强制获取 access_token 再尝试重发一次
        if (str.startsWith("{\"errcode\":40001,\"errmsg\":\"invalid credential, access_token is invalid or not latest rid:")) {
            str = sendMsg(msgobj, msgType, true);
        } else if (str.startsWith("{\"errcode\":40165,\"errmsg\":\"invalid weapp pagepath rid:")) {
            // 如果消息出现 40165 错误，发不出去时，可能需要使用 path 参数再一次重发，也许会成功，但如果不成功也将反回
            if (null == msgobj.getJSONObject("miniprogram")) {
                return str;
            }
            JSONObject miniappdata = msgobj.getJSONObject("miniprogram");
            miniappdata.remove("pagepath");
            msgobj.put("miniprogram", miniappdata);
            str = sendMsg(msgobj, msgType, false);
        }
        return str;
    }

    /**
     * 发送消息功能
     *
     * @param msgobj       消息内容OBJ
     * @param msgType      消息类型 template 表示模板消息
     * @param forceRefresh 是否强制获取access_token，值为true表示强制获取
     * @return
     * @throws Exception
     */
    private String sendMsg(JSONObject msgobj, String msgType, boolean forceRefresh) {
        String str = "";
        try {
            // 普通获取的Token，这里的token信息可能是5-20分钟内有效，具体时间是随机值，所以很坑
            String access_token = wxMpService.getAccessToken(forceRefresh);
            logger.debug("access_token ===> " + access_token);

            String apiurl = msgTypeHandler.getMsgApi(msgType);
            logger.debug("apiurl ===> " + apiurl);
            str = dohttpPost(apiurl.replace("ACCESS_TOKEN", access_token), msgobj.toJSONString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.debug("post.code ===> " + str);
        return str;
    }

    /**
     * 调用httpPost请求并将结果包装成String反回
     *
     * @param url  请求的地址
     * @param data 请求时附带的参数
     * @return
     * @throws Exception
     */
    public String dohttpPost(String url, String data) throws Exception {
        if (url.contains("ACCESS_TOKEN")) {
            String access_token = wxMpService.getAccessToken();
            url = url.replace("ACCESS_TOKEN", access_token);
            logger.debug("dohttpPost.replaceUrl.ACCESS_TOKEN ===> " + url);
        }
        return HttpUtil.post(url, data);
    }
}
